package com.ims.metnum.utils;

import com.ims.metnum.lineal.exceptions.MatrixDimensionsException;
import com.ims.metnum.lineal.exceptions.MatrixNotSquareException;

/**
 * 
 * * @author Luciano de Asteinza
 *
 */
public class Matrix implements Cloneable{

	private double[][] matrixC;
	private double[] matrixB;

	public Matrix(double[][] matrixC) {
		super();
		this.matrixC = matrixC;
		this.matrixB = new double[matrixC.length];
		for (int i = 0; i < matrixB.length; i++) {
			matrixB[i] = 0;
		}
	}
	
	public Matrix(double[][] matrixC, double[] matrixB) throws MatrixDimensionsException {
		super();
		if(matrixC.length != matrixB.length){
			throw new MatrixDimensionsException("The dimension of the coefficient matrix does not match the dimension of the matrix of independent terms");			
		}
		this.matrixC = matrixC;
		this.matrixB = matrixB;		
	}
	
	public Object clone(){
		Matrix cloneMatrix = null ;
		double[][] cloneArray = this.matrixC.clone();
		cloneMatrix = new Matrix(cloneArray);
		return cloneMatrix;
	}
	
	public boolean isSquareMatrix(){
		for (int i = 0; i<this.matrixC.length; i++){
			if(this.matrixC.length != this.matrixC[i].length){
				return false;
			}
		}
		return true;
	}
	
	public double[][] getMatrixL() throws MatrixNotSquareException{
		double[][] matrixL = null;
		if(!isSquareMatrix()){
			throw new MatrixNotSquareException("Lower triangular matrix can not be obtained because the matrix is not square");
		}else{		
			matrixL = new double[matrixC.length][matrixC.length];
			for(int i=0; i<this.matrixC.length; i++){				
				for(int j=0; j< this.matrixC[i].length; j++){
					if(i<=j){
						matrixL[i][j]=0;
					}else{
						matrixL[i][j]=matrixC[i][j];
					}
				}			
			}
		}
		return matrixL;
	}
	
	public double[][] getMatrixD() throws MatrixNotSquareException{
		double[][] matrixD = null;
		if(!isSquareMatrix()){
			throw new MatrixNotSquareException("Diagonal matrix can not be obtained because the matrix is not square");
		}else{
			matrixD = new double[matrixC.length][matrixC.length];
			for(int i=0; i<this.matrixC.length; i++){
				for(int j=0; j< this.matrixC[i].length; j++){
					if(i!=j){
						matrixD[i][j]=0;
					}else{
						matrixD[i][j] = matrixC[i][i];
					}
				}
			
			}
		}
		return matrixD;
	}
	
	public double[][] getMatrixU() throws MatrixNotSquareException{
		double[][] matrixU = null;
		if(!isSquareMatrix()){
			throw new MatrixNotSquareException("Upper triangular matrix can not be obtained because the matrix is not square");
		}else{
			matrixU = new double[matrixC.length][matrixC.length];
			for(int i=0; i<this.matrixC.length; i++){
				for(int j=0; j< this.matrixC[i].length; j++){
					if(i>=j){
						matrixU[i][j]=0;
					}else{
						matrixU[i][j]=matrixC[i][j];
					}
				}
			
			}
		}
		return matrixU;
	}

	public double[][] getMatrixC() {
		return matrixC;
	}

	public double[] getMatrixB() {
		return matrixB;
	}
	
	/**
	 * 
	 * @return true if the matrixC is Square and diagonally dominant by rows
	 */
	public boolean isDiagonallyDominant(){
		if(isSquareMatrix()){
			int sum = 0;
			for(int i = 0; i < matrixC.length; i++){
				sum = 0;
				for(int j = 0; j < matrixC.length; j++){
					if(i!=j){
						sum += Math.abs(matrixC[i][j]);
					}
				}
				if(Math.abs(matrixC[i][i])<=sum){
					return false;
				}
			}
			return true;
		}else{
			return false;
		}
	}
	
}
